package com.yzy.fly.enums;

import org.apache.poi.ss.formula.functions.T;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
import java.util.stream.Stream;

public interface IBaseEnum2<K, V> {

    default void initEnum(K code, V msg) {
        EnumContainer.putEnum(this, code, msg);
    }

    default K getCode() {
        return (K) EnumContainer.getEnum(this).getCode();
    }

    default V getMsg() {
        return (V) EnumContainer.getEnum(this).getText();
    }

    //通过code获取枚举实例
    static <K, V, R extends IBaseEnum2<K, V>> R getByCode(Class<? extends IBaseEnum2<K, V>> clazz, K code) {
//        return Stream.of(clazz.getEnumConstants())
//                .filter(tEnumBean -> tEnumBean.getCode().equals(code)).map(v -> (R) v).findAny().orElse(
//                        null);
        return getByCustomWithCode(clazz, code, (key1, key2) -> key1.equals(key2));
    }

    static <K, V, R extends IBaseEnum2<K, V>> R getByMsg(Class<? extends IBaseEnum2<K, V>> clazz, V msg) {
        return Stream.of(clazz.getEnumConstants())
                .filter(tEnumBean -> tEnumBean.getMsg().equals(msg)).map(v -> (R) v).findAny().orElse(
                        null);
    }

    static <K, V, R extends IBaseEnum2<K,V>> R getByStartsWithCode(Class<? extends IBaseEnum2<K,V>> clazz, K code) {
        return getByCustomWithCode(clazz, code, (key1, key2) -> ((String)key1).startsWith((String)key2));
    }

    static <K, V, R extends IBaseEnum2<K,V>> R getByEndsWithCode(Class<? extends IBaseEnum2<K,V>> clazz, K code) {
        return getByCustomWithCode(clazz, code, (key1, key2) -> ((String)key1).endsWith((String)key2));
    }

//    static <T, R extends IBaseEnum2<T>> R getByStartsWithMsg(Class<? extends IBaseEnum2<T>> clazz, String msg) {
//        return Stream.of(clazz.getEnumConstants())
//                .filter(tEnumBean -> msg.startsWith(tEnumBean.getMsg())).map(v -> (R) v).findAny().orElse(
//                        null);
//    }
//
//    static <T, R extends IBaseEnum2<T>> R getByEndsWithMsg(Class<? extends IBaseEnum2<T>> clazz, String msg) {
//        return Stream.of(clazz.getEnumConstants())
//                .filter(tEnumBean -> msg.endsWith(tEnumBean.getMsg())).map(v -> (R) v).findAny().orElse(
//                        null);
//    }

    /**
     * 自定义函数比较过滤
     *
     * @param clazz
     * @param msg
     * @param <T>
     * @param <R>
     * @return
     */
//    static <T, R extends IBaseEnum2<T>> R getByCustomWithMsg(Class<? extends IBaseEnum2<T>> clazz, String msg, BiFunction<String, String, Boolean> function) {
//        return Stream.of(clazz.getEnumConstants())
//                .filter(tEnumBean -> function.apply(msg, tEnumBean.getMsg())).map(v -> (R) v).findAny().orElse(
//                        null);
//    }
//
    static <K, V, R extends IBaseEnum2<K, V>> R getByCustomWithCode(Class<? extends IBaseEnum2<K,V>> clazz, K code, BiFunction<K, K, Boolean> function) {
        return Stream.of(clazz.getEnumConstants())
                .filter(tEnumBean -> function.apply(tEnumBean.getCode(), code)).map(v -> (R) v).findAny().orElse(
                        null);
    }

    //容器，用于存储枚举值
    class EnumContainer {
        private static final Map<IBaseEnum2, EnumBean> ENUM_MAP = new ConcurrentHashMap<>();

        public static <K, V> void putEnum(IBaseEnum2 baseEnum, K code, V msg) {
            ENUM_MAP.put(baseEnum, new EnumBean(code, msg));
        }

        static EnumBean getEnum(IBaseEnum2 dict) {
            return ENUM_MAP.get(dict);
        }

    }

    class EnumBean<K, V> {
        private final K code;
        private final V text;

        public EnumBean(K code, V text) {
            this.code = code;
            this.text = text;
        }

        public K getCode() {
            return this.code;
        }

        public V getText() {
            return this.text;
        }

        @Override
        public String toString() {
            return "EnumBean{" +
                    "code=" + code +
                    ", text='" + text + '\'' +
                    '}';
        }
    }
}